package com.jplus.plugin.quartz;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jplus.core.anno.boot.Configuration;
import com.jplus.core.anno.com.Autowired;
import com.jplus.core.anno.com.Order;
import com.jplus.core.core.ApplicationContext;
import com.jplus.core.core.beans.BeanDefinition;
import com.jplus.plugin.quartz.annotation.Quartz;
import com.jplus.plugin.quartz.bean.CronTriggerDto;
import com.jplus.plugin.quartz.bean.JobDetailDto;
import com.jplus.plugin.quartz.bean.SchedulerDto;

/**
 * QuartzPlugin 项目启动成功后执行;<br>
 * =================<br>
 * Demo：<br>
 * 
 * <pre>
 * &#64;Quartz(cron = "0 0 1 * * ?") // 每天凌晨1点执行一次
 * public class Demo implements Job {
 * 	public void execute(JobExecutionContext arg) throws JobExecutionException {
 * 		// TODO ...
 * 	}
 * }
 * </pre>
 * 
 * @author Yuanqy
 */
@Configuration
@Order(Integer.MAX_VALUE)
public class QuartzConfiguration {

	private final Logger logger = LoggerFactory.getLogger(QuartzConfiguration.class);
	private Scheduler scheduler;
	private @Autowired ApplicationContext context;
	private Set<Class<?>> jobs = new HashSet<>();

	@PostConstruct
	public void init() {
		List<BeanDefinition> list = context.getBeanDefinitions().listSortBeanDefinitions();
		for (BeanDefinition bd : list) {
			Class<?> cla = bd.getBeanClass();
			if (cla.isAnnotationPresent(Quartz.class)) {
				jobs.add(cla);
				logger.info("\t\t[quartz][{}]{}", cla.getAnnotation(Quartz.class).cron(), cla.getName());
			}
		}
		// =====================================
		if (jobs.size() > 0) {
			try {
				SchedulerFactory sf = new StdSchedulerFactory();
				scheduler = sf.getScheduler();
				for (Class<?> cla : jobs) {
					Quartz jt = cla.getAnnotation(Quartz.class);
					if (jt != null) {
						String cron = context.getEnvironment().getProp(jt.cron());
						SchedulerDto dto = new SchedulerDto();
						dto.setJobdetail(new JobDetailDto(jt.jobName(), jt.jobGroup(), cla));
						dto.setTrigger(new CronTriggerDto(jt.triggerName(), jt.triggerGroup(), cron));
						logger.info("==Quartz:  [{}]{}", cron, cla.getName());
						addJob(dto, scheduler);
					}
				}
				// 执行启动
				scheduler.start();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 清除(删除)所有调度数据
	 */
	@PreDestroy
	public void destroy() {
		try {
			if (!jobs.isEmpty())
				scheduler.clear();
		} catch (SchedulerException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 添加job
	 * 
	 * @param dto
	 * @throws SchedulerException
	 */
	@SuppressWarnings("unchecked")
	public void addJob(SchedulerDto dto, Scheduler scheduler) throws SchedulerException {
		addJob(scheduler, (Class<? extends Job>) dto.getJobdetail().getClas(), dto.getJobdetail().getName(),
				dto.getJobdetail().getGroup(), dto.getTrigger().getName(), dto.getTrigger().getGroup(),
				dto.getTrigger().getCron());
	}

	/**
	 * 添加 JOB
	 */
	public void addJob(Scheduler scheduler, Class<? extends Job> jobDetailCalss, String jobDetailName,
			String jobDetailGroup, String triggerName, String triggerGroup, String cron) throws SchedulerException {
		JobDetail job = JobBuilder.newJob(jobDetailCalss).withIdentity(jobDetailName, jobDetailGroup).build();
		CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(triggerName, triggerGroup)
				.withSchedule(CronScheduleBuilder.cronSchedule(cron)).build();
		scheduler.scheduleJob(job, trigger);
	}

	/**
	 * 删除JOB
	 */
	public void delJob(SchedulerDto dto, Scheduler scheduler) throws SchedulerException {
		delJob(scheduler, dto.getJobdetail().getName(), dto.getJobdetail().getGroup());
	}

	/**
	 * 删除JOB
	 */
	public void delJob(Scheduler scheduler, String jobName, String jobGroup) throws SchedulerException {
		JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
		scheduler.deleteJob(jobKey);
	}

	/**
	 * 暂停JOB
	 */
	public void pauseJob(SchedulerDto dto, Scheduler scheduler) throws SchedulerException {
		pauseJob(scheduler, dto.getJobdetail().getName(), dto.getJobdetail().getGroup());
	}

	/**
	 * 暂停JOB
	 */
	public void pauseJob(Scheduler scheduler, String jobName, String jobGroup) throws SchedulerException {
		JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
		scheduler.pauseJob(jobKey);
	}

	/**
	 * 恢复JOB
	 */
	public void resumeJob(SchedulerDto dto, Scheduler scheduler) throws SchedulerException {
		resumeJob(scheduler, dto.getJobdetail().getName(), dto.getJobdetail().getGroup());
	}

	/**
	 * 恢复JOB
	 */
	public void resumeJob(Scheduler scheduler, String jobName, String jobGroup) throws SchedulerException {
		JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
		scheduler.resumeJob(jobKey);
	}

}
